package org.example.processors;

import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.*;
import org.example.support.Environment;
import org.example.utils.ProcessUtil;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.tools.Diagnostic;

public abstract class BaseProcessor extends AbstractProcessor {
    static {
        Environment.addOpens();
    }

    /**
     * 用于在编译器打印消息的组件
     */
    Messager messager;

    /**
     * 语法树
     */
    JavacTrees trees;

    /**
     * 用来构造语法树节点
     */
    TreeMaker treeMaker;

    /**
     * 用于创建标识符的对象
     */
    Names names;

    /**
     * 字段的语法树节点的集合
     */
    List<JCTree.JCVariableDecl> fieldJcVariables;

    @Override
    public final synchronized void init(ProcessingEnvironment processingEnv) {
        Environment.addOpens();
        processingEnv = Environment.getJavacProcessingEnvironment(processingEnv);
        super.init(processingEnv);
        this.messager = processingEnv.getMessager();
        this.trees = JavacTrees.instance(processingEnv);
        Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
        this.treeMaker = TreeMaker.instance(context);
        this.names = Names.instance(context);
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latest();
    }

    /**
     * 进行一些初始化工作
     *
     * @param jcClass 类的语法树节点
     */
    protected void before(JCTree.JCClassDecl jcClass) {
        this.fieldJcVariables = ProcessUtil.getJcVariablesWithFinal(jcClass);
    }

    /**
     * 进行一些清理工作
     */
    protected void after() {
        this.fieldJcVariables = null;
    }


    /**
     * 创建范型类型，如<String,Object>
     *
     * @param typeNames 泛型的类型名称
     */
    public List<JCTree.JCExpression> createTypeArgs(String... typeNames) {
        ListBuffer<JCTree.JCExpression> typeArgs = new ListBuffer<>();
        for (String typeName : typeNames) {
            typeArgs.append(treeMaker.Ident(names.fromString(typeName)));
        }
        return typeArgs.toList();
    }

    public List<JCTree.JCExpression> createTypeArgs(Name... typeNames) {
        ListBuffer<JCTree.JCExpression> typeArgs = new ListBuffer<>();
        for (Name typeName : typeNames) {
            typeArgs.append(treeMaker.Ident(typeName));
        }
        return typeArgs.toList();
    }

    /**
     * 创建(变量、方法)类型 如Map<String,Object>
     *
     * @param typeName     类型名称
     * @param genericTypes 泛型类型列表
     */
    public JCTree.JCTypeApply createTypeApply(String typeName, List<JCTree.JCExpression> genericTypes) {
        String[] typeNames = typeName.split("\\.");

        JCTree.JCExpression type = null;
        for (String name : typeNames) {
            if (type == null) {
                type = treeMaker.Ident(names.fromString(name));
            } else {
                type = treeMaker.Select(type, names.fromString(name));
            }
        }

        return treeMaker.TypeApply(
            type,
            genericTypes
        );
    }

    /**
     * 直接通过类型创建(变量、方法)类型 如Map<String,Object>
     *
     * @param type         类型名称
     * @param genericTypes 泛型类型列表
     * @return
     */
    public JCTree.JCTypeApply createTypeApply(JCTree.JCExpression type, List<JCTree.JCExpression> genericTypes) {
        return treeMaker.TypeApply(
            type,
            genericTypes
        );
    }

    /**
     * 创建对象 如 new HashMap<String,Object>
     *
     * @param classType 对象类型
     * @param params    new对象参数
     * @return
     */
    public JCTree.JCNewClass createNewClass(JCTree.JCExpression classType, List<JCTree.JCExpression> params) {
        if (params == null) {
            params = List.nil();
        }
        return treeMaker.NewClass(
            null,
            List.nil(),
            classType, //对象类型
            params,    //new时的参数
            null
        );
    }

    /**
     * 创建变量初始化赋值的语句，如 Map<String,Object> map = new HashMap<>()
     *
     * @param varName    变量名
     * @param varType    变量类型
     * @param objectType 对象类型
     */
    public JCTree.JCVariableDecl createVarAssignInit(String varName, JCTree.JCTypeApply varType, JCTree.JCNewClass objectType) {
        return treeMaker.VarDef(
            treeMaker.Modifiers(Flags.BLOCK),
            names.fromString(varName),
            varType, objectType
        );
    }

    /**
     * 创建调用表达式，如map.put("xxx","xxx")
     *
     * @param varName
     * @param funcName
     * @param params
     */
    public JCTree.JCMethodInvocation createMethodInvocation(String varName, String funcName, List<JCTree.JCExpression> params) {
        return treeMaker.Apply(
            //没有类型参数
            List.nil(),
            //选择器map.put
            treeMaker.Select(
                treeMaker.Ident(names.fromString(varName)),
                names.fromString(funcName)
            ),
            params
        );
    }

    public void log(String message, Object... args) {
        this.messager.printMessage(Diagnostic.Kind.NOTE, String.format(message, args));
    }

    public void fatalError(String msg) {
        this.messager.printMessage(Diagnostic.Kind.ERROR, "FATAL ERROR: " + msg);
    }

    public void error(String msg, Element element, AnnotationMirror annotation) {
        this.messager.printMessage(Diagnostic.Kind.ERROR, msg, element, annotation);
    }

    public void warning(String msg, Element element, AnnotationMirror annotation) {
        this.messager.printMessage(Diagnostic.Kind.WARNING, msg, element, annotation);
    }
}
